package common.library.utils;

import org.json.JSONObject;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;

import lombok.var;

/**
 * 以下安卓不可用，请使用该工具类中封装的方法
 * HttpURLConnection.getResponseMessage();
 * HttpURLConnection.getInputStream();
 * 注意申请Manifest.permission.INTERNET,
 */
public class HttpUtil {

    public static InputStream getInputStream(HttpURLConnection connection) {
        try {
            InputStream inputStream = connection.getInputStream();
            ByteArrayOutputStream rawStream = new ByteArrayOutputStream();
            int _byte;
            while ((_byte = inputStream.read()) != -1)
                rawStream.write(_byte);
            inputStream.close();
            rawStream.flush();
            var stream = new ByteArrayInputStream(rawStream.toByteArray());
            rawStream.close();
            return stream;
        } catch (Exception ex) {
            ex.printStackTrace();
            return null;
        }
    }

    public static byte[] getBytes(HttpURLConnection connection) {
        try {
            InputStream inputStream = connection.getInputStream();
            ByteArrayOutputStream streamWriter = new ByteArrayOutputStream();
            int _byte;
            while ((_byte = inputStream.read()) != -1)
                streamWriter.write(_byte);
            inputStream.close();
            var bytes = streamWriter.toByteArray();
            streamWriter.close();
            return bytes;
        } catch (Exception ex) {
            ex.printStackTrace();
            return null;
        }
    }

    public static String getResponseMessage(HttpURLConnection connection) {
        try {
            InputStream inputStream = connection.getInputStream();
            ByteArrayOutputStream streamWriter = new ByteArrayOutputStream();
            int _byte;
            while ((_byte = inputStream.read()) != -1)
                streamWriter.write(_byte);
            inputStream.close();
            var message = streamWriter.toString();
            streamWriter.close();
            return message;
        } catch (Exception ex) {
            ex.printStackTrace();
            return null;
        }
    }

    enum Method {
        get,
        post,
        put
    }

    static HttpURLConnection send(String uri, Method method, String data, Map<String, String> headers, int timeout) {
        try {
            LogUtil.debug("Try to {} to {}", method, uri);
            URL url = new URL(uri);
            final HttpURLConnection connection = (HttpURLConnection) url.openConnection();
            switch (method) {
                case post:
                    connection.setRequestMethod("POST");
                    break;
                case put:
                    connection.setRequestMethod("PUT");
                    break;
                case get:
                default:
                    connection.setRequestMethod("GET");
                    break;
            }

            if (headers != null)
                for (Map.Entry<String, String> header : headers.entrySet())
                    connection.setRequestProperty(header.getKey(), header.getValue());

            if (timeout != 0)
                connection.setConnectTimeout(timeout);

            if (data != null) {
                OutputStream outputStream = connection.getOutputStream();//如果卡在这里，说明链接不可用，设置timeout没用的，可以尝试把http服务的localhost换成ip
                outputStream.write(data.getBytes());
                outputStream.close();
            }

            connection.connect();
            LogUtil.debug("Success to {} to {} response code {}", method, uri, connection.getResponseCode());
            return connection;
        } catch (Exception ex) {
            LogUtil.debug("Fail to {} to {} error {}", method, uri, ex);
            return null;
        }
    }

    public static final boolean checkStatus(String url, float timeoutSeconds) {
        try {
            return send(url, Method.get, null, null, (int) (timeoutSeconds * 1000)).getResponseCode() == 200;
        } catch (Exception ex) {
            LogUtil.error(ex);
            return false;
        }
    }

    public static HttpURLConnection get(String uri, Map<String, String> headers) {
        return send(uri, Method.get, null, headers, 0);
    }

    public static HttpURLConnection get(String url) {
        return get(url, null);
    }

    public static String getString(String uri, Map<String, String> headers) {
        HttpURLConnection connection = get(uri, headers);
        //String result = connection.getResponseMessage();//安卓不可用
        String result = getResponseMessage(connection);
        connection.disconnect();
        return result;
    }

    public static String getString(String url) {
        return getString(url, null);
    }

    public static HttpURLConnection post(String uri, String data, Map<String, String> headers) {
        return send(uri, Method.post, data, headers, 0);
    }

    public static HttpURLConnection post(String url, String data) {
        return post(url, data, null);
    }

    public static String postJson(String url, String json) {
        Map<String, String> headers = new HashMap();
        headers.put("Content-Type", "application/json");
        HttpURLConnection connection = post(url, json, headers);
        //String result = connection.getResponseMessage();//安卓不可用
        String result = getResponseMessage(connection);
        connection.disconnect();
        return result;
    }

    public static String post(String url, JSONObject data) {
        return postJson(url, data.toString());
    }

    public static InputStream download(String url) {
        var result = get(url);
        return getInputStream(result);
    }

    public static HttpURLConnection put(String uri, String data, Map<String, String> headers) {
        return send(uri, Method.put, data, headers, 0);
    }

    public static String putJson(String url, String json) {
        Map<String, String> headers = new HashMap();
        headers.put("Content-Type", "application/json");
        HttpURLConnection connection = put(url, json, headers);
        //String result = connection.getResponseMessage();//安卓不可用
        String result = getResponseMessage(connection);
        connection.disconnect();
        return result;
    }

    public static void SendToDebugServer(final Object value) {
        //安卓不允许http被主程序调用
        ThreadUtil.start(new Runnable() {
            @Override
            public void run() {
                putJson("http://192.168.20.133:5000/api/Debug/Put", JsonUtil.serialization(value));
            }
        });
    }
}
